import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

//      Serializable 序列化接口：把一个对象转变为字符串
//  ArrayList与顺序表
//  ArrayList底层就是一个数组
public class TestDemo2 {
    public static void main1(String[] args) {
//        1. 三种构造方法
        List<String> list = new ArrayList<>();//接口可以引用具体的实例对象
        ArrayList<String> list2 = new ArrayList<>();//直接通过实例化具体的类 可以不通过接口

//        2.
        List<String> list3 = new ArrayList<>(20);//初始容量
        System.out.println(list3.size());//0
        list3.add("hello");
        list3.add("world");
        System.out.println(list3.size());//2
        System.out.println(list3);//[hello, world]


        ArrayList<String> list4 = new ArrayList<>();
        list4.add("cat");
        list4.add("dog");
        list4.add("pig");
//        打印方式 四种
        System.out.println(list4);//[cat, dog, pig]
        System.out.println("========2=========");
        for (int i = 0; i < list4.size(); i++) {
            System.out.print(list4.get(i) + " ");//get 返回类型是E  也就是定义的String
        }//cat dog pig

        System.out.println();
        System.out.println("========3=========");
        // 因为ArrayList实现Iterable接口可以使用foreach打印
        for (String str : list4) {
            System.out.print(str + " ");//cat dog pig
        }

        System.out.println();
        System.out.println("========4迭代器打印======");//
        Iterator<String> it = list4.iterator();//查看源码可知道 我们得用Iterator<E>接收
        while (it.hasNext()) {
            System.out.print(it.next() + " ");//cat dog pig
//            ArrayList底层就是一个数组 it指向第一个元素的前一个位置
        }

        System.out.println();
        System.out.println("========4迭代器List打印======");//
        ListIterator<String> it2 = list4.listIterator();


        while (it2.hasNext()) {
            System.out.print(it2.next() + " ");//cat dog pig
        }

//        ListIterator和Iterator区别
//        1.Iterator是ListIterator的父类   ListIterator继承Iterator
//        2.ListIterator还具备add功能和set功能
    }


//    迭代器 set() add()使用
    public static void main2(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("cat");
        list.add("pig");
        list.add("dog");
//        Iterator迭代器没有add 和 set方法
        ListIterator<String> listIt = list.listIterator();
        listIt.add("world");//因为是从-1位置开始  就是 -1>hello>cat>pig>dog
        while(listIt.hasNext()){
//            String next = listIt.next();
//            if(next.equals("pig")){
//                listIt.set("cyl");
//            }

            if (listIt.next().equals("pig")) {
                listIt.set("cyl");
            }
        }
        System.out.println(list);
//       [world, hello, cat, cyl, dog]
    }


    public static void main3(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("cat");
        list.add("pig");
        Iterator<String> it = list.iterator();

//        错误的

//        while (it.hasNext()) {
//            it.remove();//IllegalStateException  报错
//            System.out.print(it.next() + " ");
//        }

//        为什么会报错  下面写
//        我们在用迭代remove()时，可能会因为没有it.next();这一行
//        地抛出IllegalStateException异常，原因是通过terator来删
//        除集合中某一个不满足条件的元素时
//        解决方法
//        首先需要使用next方法法代出集合中的元素，然后才能调用remove方法
//        否则集合可能会因为对同一个terator remove
//        了多次而抛出java .lang lalStateExceptin异常。



//        while (it.hasNext()) {
//            String ret = it.next();
//            if (ret.equals("hello")){
//                it.remove();
//            }else {
//                System.out.print(ret + " ");//dog pig
//            }
//        }



//        while (it.hasNext()) {
//            String ret = it.next();
//            if (ret.equals("hello")){
//                it.add();//error
//                it.set();//error
//            }else {
//                System.out.print(ret + " ");//dog pig
//            }
//        }
        //        Iterator迭代器没有add 和 set方法
    }

    public static void main4(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("pig");
        list.add("cat");
        ListIterator<String> it = list.listIterator();

        while (it.hasNext()) {
            String ret = it.next();
            if (ret.equals("pig")){
                it.add("cyl");
            }else {
                System.out.print(ret + " ");//hello cat
            }
        }
        System.out.println();
        System.out.println(list);//[hello, pig, cyl, cat]
    }





    public static void main5(String[] args) {
//        不是线程安全
        ArrayList<String> list = new ArrayList();


        list.add("hello");
        list.add("pig");
        list.add("cat");

        ListIterator<String> it = list.listIterator();
//        下面会报错
        while (it.hasNext()) {
            String ret = it.next();
            if (ret.equals("pig")){
                list.add("cyl");//这里是list.
            }else {
                System.out.print(ret + " ");//hello cat
            }
        }
    }


    public static void main6(String[] args) {
//          线程安全
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();


        list.add("hello");
        list.add("pig");
        list.add("cat");


        ListIterator<String> it = list.listIterator();
//        下面不会报错 可以运行
        while (it.hasNext()) {
            String ret = it.next();
            if (ret.equals("pig")){
                list.add("cyl");//这里是list.
            }else {
                System.out.print(ret + " ");//hello cat
            }
        }
        System.out.println();
        System.out.println(list);//[hello, pig, cat, cyl]
    }




    public static void main7(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");//add默认放到数组最后一个位置
        System.out.println(list);//[a, b, c]
        list.add(0,"pig");//[pig, a, b, c]
        System.out.println(list);


//        整体list放进去
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("cat");
        list2.add("dog");
        list.addAll(list2);
        System.out.println(list);//[pig, a, b, c, cat, dog]
    }



    public static void main8(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        System.out.println(list);//[a, b, c, d, e, f]
        //    删除
        String ret = list.remove(0);
        System.out.println(ret);//a
        System.out.println(list);//[b, c, d, e, f]

//        是否存在有就删  这些都有放回值 我直接用println打印
        System.out.println(list.remove("a"));//false
        System.out.println(list.remove("d"));//true
        System.out.println(list);//[b, c, e, f]

//        更新
        System.out.println(list.set(1,"a"));
        System.out.println(list);//[b, a, e, f]

//        截取
        System.out.println(list.subList(1,3));//[a, e]  左闭右开

    }


    public static void main9(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("dog");
        list.add("cat");
        list.add("pig");
        list.add("cyl");
        List<String> sub = list.subList(1,4);
        System.out.println(sub);//[world, dog, cat]
        System.out.println(list);//[hello, world, dog, cat, pig, cyl]
        System.out.println("==================");
        sub.set(1,"no");
        System.out.println(sub);//[world, no, cat]
        System.out.println(list);//[hello, world, no, cat, pig, cyl]
//        并不是直接截取出 生成一个新表 而是截取出第一个元素的地址
    }


    public static void main10(String[] args) {


        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 100; i++){
            list.add(i);
        }//这段代码 问题  有隐式扩容
    }




    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();//初始大小是几？ 答案是0     alt+鼠标右键
        list.add("hello");//当第一次存放数据元素的时候 顺序表被分配大小为10
//        结论：
//          如果ArrayList调用，不带参数的构造方法，那么顺序表的大小是0.      当第一-次add的时候整个顺序表才变为了10;
//          当这10个放满了，开始扩容，以1.5倍的方式进行扩容。
//          如果调用的是给定容量的构造方法，那么你的顺序表的大小，就是你给定的容量，放满了还是1.5倍进行扩容。



        System.out.println(list);
//        发现底层虽然是数组 但是当前这个数组 没有大小
//        既然数组大小是0 那么存放这个元素的时候 为什么可以成功 没有越界
//          查看add源码   ensureCapacityInternal(size + 1); 这段代码 真正的扩容
//          看板书理解List的板书
        ArrayList<String> list2 = new ArrayList<>(20);//初始大小是指定的20
    }

}
